#include "Cliente.h"

Cliente * Cliente::instance = NULL;

Cliente::Cliente( const char * archivo, char letraPeticion, char letraRespuesta ) :
	colaPeticion(archivo, letraPeticion), colaRespuesta(archivo, letraRespuesta) {
	this->id = getpid();
}

Cliente::~Cliente() {
}

Cliente * Cliente::getInstance(){
	if(instance == NULL)
		instance = new Cliente(ARCHIVO_COLAS, LETRA_CONSULTAS, LETRA_RESPUESTAS);
	return instance;
}

void Cliente::destroy() {
	if (instance != NULL) {
		delete instance;
		instance = NULL;
	}
}

const list<Persona> * Cliente::realizarBusqueda(criterio_busqueda critBusq, tipo_condicion cond, string valor){
	ConsultaType consulta;
	RespuestaType respuesta;

	if(critBusq == cbNombre && valor.length() > MAX_NOMBRE ){
		stringstream error;
		error << "Nombre muy largo, debe contener menos de ";
		error << MAX_NOMBRE;
		error << " caracteres";
		throw ValorInvalidoException(error.str());
	}
	if(critBusq == cbDireccion && valor.length() > MAX_DIRECCION ){
		stringstream error;
		error << "Direccion muy largo, debe contener menos de ";
		error << MAX_DIRECCION;
		error << " caracteres";
		throw ValorInvalidoException(error.str());
	}
	if(critBusq == cbNumero && valor.length() > MAX_TELEFONO ){
		stringstream error;
		error << "Telefono muy largo, debe contener menos de ";
		error << MAX_TELEFONO;
		error << " caracteres";
		throw  ValorInvalidoException(error.str());
	}
	consulta.mtype = this->id;
	consulta.tipo = tSelect;
	strcpy(consulta.tabla, TABLA_PERSONAS);
	consulta.columna = critBusq;
	consulta.condicion = cond;
	strcpy(consulta.valor, valor.c_str());

	this->resultadoBusqueda.clear();
	this->colaPeticion.escribir(consulta);

	bool fin = false;
	while (!fin) {
		int error = this->colaRespuesta.leer(this->id, &respuesta);
		fin = respuesta.fin || error < 0;
		if (!fin) {
			Persona persona(respuesta.persona);
			this->resultadoBusqueda.push_back(persona);
		}
	}

	return &this->resultadoBusqueda;
}


void Cliente::insertarPersona(Persona persona){
	ConsultaType consulta;
	RespuestaType respuesta;

	if(persona.getNombre().length() > MAX_NOMBRE ){
		stringstream error;
		error << "Nombre muy largo, debe contener menos de ";
		error << MAX_NOMBRE;
		error << " caracteres";
		throw  ValorInvalidoException(error.str());
	}
	if(persona.getDireccion().length() > MAX_DIRECCION ){
		stringstream error;
		error << "Direccion muy largo, debe contener menos de ";
		error << MAX_DIRECCION;
		error << " caracteres";
		throw  ValorInvalidoException(error.str());
	}
	if(persona.getTelefono().length() > MAX_TELEFONO ){
		stringstream error;
		error << "Telefono muy largo, debe contener menos de ";
		error << MAX_TELEFONO;
		error << " caracteres";
		throw  ValorInvalidoException(error.str());
	}

	strcpy(consulta.persona.nombre,persona.getNombre().c_str());
	strcpy(consulta.persona.direccion,persona.getDireccion().c_str());
	strcpy(consulta.persona.telefono,persona.getTelefono().c_str());
	strcpy(consulta.tabla, TABLA_PERSONAS);
	consulta.mtype = this->id;
	consulta.tipo = tInsert;

	this->colaPeticion.escribir(consulta);
	int error = this->colaRespuesta.leer(this->id, &respuesta);
	if (error >= 0) {
		if(respuesta.error > 0)
			throw ErrorGestorException(respuesta.mensaje);
	} else {
		throw ErrorGestorException("El Gestor no esta corriendo");
	}
}

string Cliente::actualizarPersona(criterio_busqueda criterio, tipo_condicion tipoCondicion, string valorSeleccion, criterio_busqueda columnaActualizar, string nuevoValor){
	ConsultaType consulta;
	RespuestaType respuesta;
	if(criterio == cbNombre && valorSeleccion.length() > MAX_NOMBRE ){
		stringstream error;
		error << "Nombre muy largo, debe contener menos de ";
		error << MAX_NOMBRE;
		error << " caracteres";
		throw  ValorInvalidoException(error.str());
	}
	if(criterio == cbDireccion && valorSeleccion.length() > MAX_DIRECCION ){
		stringstream error;
		error << "Direccion muy larga, debe contener menos de ";
		error << MAX_DIRECCION;
		error << " caracteres";
		throw  ValorInvalidoException(error.str());
	}
	if(criterio == cbNumero && valorSeleccion.length() > MAX_TELEFONO  ){
		stringstream error;
		error << "Telefono muy largo, debe contener menos de ";
		error << MAX_TELEFONO;
		error << " caracteres";
		throw  ValorInvalidoException(error.str());
	}

	if(columnaActualizar == cbNombre && nuevoValor.length() > MAX_NOMBRE ){
		stringstream error;
		error << "Nombre muy largo, debe contener menos de ";
		error << MAX_NOMBRE;
		error << " caracteres";
		throw  ValorInvalidoException(error.str());
	}
	if(columnaActualizar == cbDireccion && nuevoValor.length() > MAX_DIRECCION ){
		stringstream error;
		error << "Direccion muy larga, debe contener menos de ";
		error << MAX_DIRECCION;
		error << " caracteres";
		throw  ValorInvalidoException(error.str());
	}
	if(columnaActualizar == cbNumero && nuevoValor.length() > MAX_TELEFONO  ){
		stringstream error;
		error << "Telefono muy largo, debe contener menos de ";
		error << MAX_TELEFONO;
		error << " caracteres";
		throw  ValorInvalidoException(error.str());
	}

	consulta.tipo = tUpdate;
	consulta.mtype = this->id;
	strcpy(consulta.tabla, TABLA_PERSONAS);
	consulta.condicion = tipoCondicion;
	consulta.columna = criterio;
	consulta.columnaUp = columnaActualizar;
	strcpy(consulta.valor, valorSeleccion.c_str());
	strcpy(columnaActualizar == cbNombre? consulta.persona.nombre :
			columnaActualizar == cbDireccion? consulta.persona.direccion :
					consulta.persona.telefono, nuevoValor.c_str());

	this->colaPeticion.escribir(consulta);
	int error = this->colaRespuesta.leer(this->id, &respuesta);
	if (error >= 0) {
		if(respuesta.error > 0){
			throw ErrorGestorException(respuesta.mensaje);
		}
	} else {
		throw ErrorGestorException("El Gestor no esta corriendo.");
	}
	return string(respuesta.mensaje);


}

string Cliente::borrarPersona(criterio_busqueda criterio, tipo_condicion criterioComparacion, string valorSeleccion){
	ConsultaType consulta;
	RespuestaType respuesta;
	if(criterio == cbNombre && valorSeleccion.length() > MAX_NOMBRE ){
		stringstream error;
		error << "Nombre muy largo, debe contener menos de ";
		error << MAX_NOMBRE;
		error << " caracteres";
		throw  ValorInvalidoException(error.str());
	}
	if(criterio == cbDireccion && valorSeleccion.length() > MAX_DIRECCION ){
		stringstream error;
		error << "Direccion muy larga, debe contener menos de ";
		error << MAX_DIRECCION;
		error << " caracteres";
		throw  ValorInvalidoException(error.str());
	}
	if(criterio == cbNumero && valorSeleccion.length() > MAX_TELEFONO  ){
		stringstream error;
		error << "Telefono muy largo, debe contener menos de ";
		error << MAX_TELEFONO;
		error << " caracteres";
		throw  ValorInvalidoException(error.str());
	}

	consulta.tipo = tDelete;
	consulta.mtype = this->id;
	strcpy(consulta.tabla, TABLA_PERSONAS);
	consulta.columna = criterio;
	consulta.condicion = criterioComparacion;
	strcpy(consulta.valor, valorSeleccion.c_str());

	this->colaPeticion.escribir(consulta);
	int error = this->colaRespuesta.leer(this->id, &respuesta);
	if (error >= 0) {
		if(respuesta.error > 0){
			throw ErrorGestorException(respuesta.mensaje);
		}
	} else {
		throw ErrorGestorException("El Gestor no esta corriendo.");
	}
	return string(respuesta.mensaje);
}

